home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / tasker / tasker.c < prev   
C/C++ Source or Header  |  1997-07-22  |  9KB  |  460 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: tasker.c,v 1.4 1997/07/09 13:55:21 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34. *    tasker.c
  35. *
  36. *    Example tasker task to demonstrate and verify the protocol.
  37. *
  38. *    06 Mar 1994  Robert Manchek
  39. */
  40.  
  41.  
  42. #ifdef HASSTDLIB
  43. #include <stdlib.h>
  44. #endif
  45. #include <stdio.h>
  46. #include <signal.h>
  47. #include <sys/types.h>
  48. #ifdef    IMA_LINUX
  49. #include <linux/time.h>
  50. #endif
  51. #include <pvm3.h>
  52. #include <sys/wait.h>
  53. #include <sys/resource.h>
  54. #ifdef    IMA_RS6K
  55. #include <sys/select.h>
  56. #endif
  57. #ifdef    SYSVSTR
  58. #include <string.h>
  59. #else
  60. #include <strings.h>
  61. #endif
  62. #include <pvmproto.h>
  63.  
  64. #if defined(SYSVBFUNC)
  65. #include <memory.h>
  66. #define BZERO(d,n)      memset(d,0,n)
  67. #define BCMP(s,d,n)     memcmp(d,s,n)
  68. #define BCOPY(s,d,n)    memcpy(d,s,n)
  69.  
  70. #else
  71. #define BZERO(d,n)      bzero(d,n)
  72. #define BCMP(s,d,n)     bcmp(s,d,n)
  73. #define BCOPY(s,d,n)    bcopy(s,d,n)
  74. #endif
  75.  
  76. #define    LISTPUTAFTER(o,n,f,r) \
  77.     { (n)->f=(o)->f; (n)->r=o; (o)->f->r=n; (o)->f=n; }
  78. #define    LISTPUTBEFORE(o,n,f,r) \
  79.     { (n)->r=(o)->r; (n)->f=o; (o)->r->f=n; (o)->r=n; }
  80. #define    LISTDELETE(e,f,r) \
  81.     { (e)->f->r=(e)->r; (e)->r->f=(e)->f; (e)->r=(e)->f=0; }
  82.  
  83. #define    TALLOC(n,t,g)    (t*)malloc((n)*sizeof(t))
  84. #define    FREE(p)    free((char *)p)
  85. #define    STRALLOC(s)            strcpy(TALLOC(strlen(s)+1,char,"str"),s)
  86.  
  87. #ifndef    DEBUG
  88. #define    DEBUG    0
  89. #endif
  90.  
  91.  
  92. /*
  93. *     to collect stats from exited tasks
  94. */
  95.  
  96. struct deaddata {
  97.     int dd_pid;                /* process id */
  98.     int dd_es;                /* unix exit status */
  99.     struct timeval dd_ut;    /* user time used */
  100.     struct timeval dd_st;    /* system time used */
  101. };
  102.  
  103. /*
  104. *    to track live tasks
  105. */
  106.  
  107. struct task {
  108.     struct task *t_link, *t_rlink;
  109.     int t_tid;
  110.     int t_pid;
  111. };
  112.  
  113.  
  114. int debug = DEBUG;
  115. struct deaddata *deads = 0;        /* circ queue of dead task data */
  116. int ndead = 1000;                /* len of deads */
  117. int rdead = 0;                    /* read ptr for deads */
  118. int wdead = 0;                    /* write ptr for deads */
  119. struct task *mytasks = 0;
  120.  
  121.  
  122. /**************************
  123. *  task management stuff  *
  124. *                         *
  125. **************************/
  126.  
  127. void
  128. task_init()
  129. {
  130.     mytasks = TALLOC(1, struct task, 0);
  131.     mytasks->t_link = mytasks->t_rlink = mytasks;
  132.     mytasks->t_tid = 0;
  133.     mytasks->t_pid = 0;
  134. }
  135.  
  136.  
  137. /*    task_new()
  138. *
  139. *    Make a new task descriptor, add to list.
  140. */
  141.  
  142. struct task *
  143. task_new(tid, pid)
  144.     int tid, pid;
  145. {
  146.     struct task *tp;
  147.  
  148.     if (!(tp = TALLOC(1, struct task, 0))) {
  149.         fprintf(stderr, "task_new() can't get memory\n");
  150.         exit(1);
  151.     }
  152.     tp->t_tid = tid;
  153.     tp->t_pid = pid;
  154.     LISTPUTBEFORE(mytasks, tp, t_link, t_rlink);
  155.     return tp;
  156. }
  157.  
  158.  
  159. void
  160. task_free(tp)
  161.     struct task *tp;
  162. {
  163.     LISTDELETE(tp, t_link, t_rlink);
  164.     FREE(tp);
  165. }
  166.  
  167.  
  168. /*    task_find()
  169. *
  170. *    Find a task by its tid.
  171. */
  172.  
  173. struct task *
  174. task_find(tid)
  175.     int tid;
  176. {
  177.     struct task *tp;
  178.  
  179.     for (tp = mytasks->t_link; tp != mytasks; tp = tp->t_link)
  180.         if (tp->t_tid == tid)
  181.             return tp;
  182.     return (struct task*)0;
  183. }
  184.  
  185.  
  186. /*    task_findpid()
  187. *
  188. *    Find a task by its pid.
  189. */
  190.  
  191. struct task *
  192. task_findpid(pid)
  193.     int pid;
  194. {
  195.     struct task *tp;
  196.  
  197.     for (tp = mytasks->t_link; tp != mytasks; tp = tp->t_link)
  198.         if (tp->t_pid == pid)
  199.             return tp;
  200.     return (struct task*)0;
  201. }
  202.  
  203.  
  204. void
  205. task_dump()
  206. {
  207.     struct task *tp;
  208.  
  209.     for (tp = mytasks->t_link; tp != mytasks; tp = tp->t_link)
  210.         printf("t%x pid %d\n", tp->t_tid, tp->t_pid);
  211. }
  212.  
  213.  
  214. /******************
  215. *  general stuff  *
  216. *                 *
  217. ******************/
  218.  
  219. /*    reap()
  220. *
  221. *    Child task has exited; get its stats and put in the fifo.
  222. */
  223.  
  224. void
  225. reap(sig)
  226.     int sig;
  227. {
  228.     int pid;
  229.     int es = 0;
  230. #ifndef NOWAIT3
  231.     struct rusage rus;
  232. #endif
  233.  
  234.     sig = sig;
  235.  
  236. #ifdef    NOWAIT3
  237. #ifdef    NOWAITPID
  238.     if ((pid = wait(&es)) > 0)
  239. #else
  240.     while ((pid = waitpid(-1, &es, WNOHANG)) > 0)
  241. #endif
  242. #else    /*NOWAIT3*/
  243.     while ((pid = wait3(&es, WNOHANG, &rus)) > 0)
  244. #endif    /*NOWAIT3*/
  245.     {
  246. /*
  247.         deads[wdead] = pid;
  248. */
  249. #ifdef NOWAIT3
  250.         deads[wdead].dd_ut.tv_sec = 0;
  251.         deads[wdead].dd_ut.tv_usec = 0;
  252.         deads[wdead].dd_st.tv_sec = 0;
  253.         deads[wdead].dd_st.tv_usec = 0;
  254. #else
  255.         deads[wdead].dd_ut = rus.ru_utime;
  256.         deads[wdead].dd_st = rus.ru_stime;
  257. #endif
  258.         deads[wdead].dd_pid = pid;
  259.         deads[wdead].dd_es = es;
  260.         if (++wdead >= ndead)
  261.             wdead = 0;
  262.     }
  263. #ifdef    SYSVSIGNAL
  264.     (void)signal(SIGCLD, reap);
  265. #endif
  266. }
  267.  
  268.  
  269. main(argc, argv)
  270.     int argc;
  271.     char **argv;
  272. {
  273.     int otid;            /* tid of request */
  274.     int tag;            /* message tag */
  275.     int *fdlist;        /* to get libpvm fd list */
  276.     fd_set rfds, fds;
  277.     int nfds;
  278.     int mid;
  279.     struct task *tp;
  280.  
  281.     pvm_mytid();                        /* become a task */
  282.  
  283.     pvm_setopt(PvmResvTids, 1);            /* allow reserved messages */
  284.  
  285.     pvm_reg_tasker();                    /* register as tasker */
  286.  
  287.     pvm_setopt(PvmRoute, PvmDontRoute);    /* no freaks talking to me */
  288.  
  289.     /* get the pvmd socket fd so we can wait with select() */
  290.  
  291.     pvm_getfds(&fdlist);
  292.     FD_ZERO(&rfds);
  293.     FD_SET(fdlist[0], &rfds);
  294.     nfds = fdlist[0] + 1;
  295.  
  296.     /* install child signal handler */
  297.  
  298.     deads = TALLOC(ndead, struct deaddata, 0);
  299.     BZERO((char*)deads, ndead * sizeof(struct deaddata));
  300.  
  301. #ifndef    SYSVSIGNAL
  302.     (void)signal(SIGCHLD, reap);
  303. #else
  304.     (void)signal(SIGCLD, reap);
  305. #endif
  306.  
  307.     task_init();
  308.  
  309.     while (1) {
  310. /*
  311.         task_dump();
  312. */
  313.         fds = rfds;
  314.         select(nfds, &fds, (fd_set*)0, (fd_set*)0, (struct timeval*)0);
  315.  
  316.     /* clean up after any croaked processes */
  317.  
  318.         while (rdead != wdead) {
  319.             if (tp = task_findpid(deads[rdead].dd_pid)) {
  320.                 if (debug)
  321.                     printf("Exit t%x pid %d\n", tp->t_tid, tp->t_pid);
  322.  
  323.                 pvm_packf("%+ %d %d %d %d %d %d",
  324.                         PvmDataFoo,
  325.                         tp->t_tid,
  326.                         deads[rdead].dd_es,
  327.                         (int)deads[rdead].dd_ut.tv_sec,
  328.                         (int)deads[rdead].dd_ut.tv_usec,
  329.                         (int)deads[rdead].dd_st.tv_sec,
  330.                         (int)deads[rdead].dd_st.tv_usec);
  331.                 pvm_send(0x80000000, SM_TASKX);
  332.                 task_free(tp);
  333.             }
  334.             if (++rdead >= ndead)
  335.                 rdead = 0;
  336.         }
  337.  
  338.     /* check for task-start messages */
  339.  
  340.         while ((mid = pvm_nrecv(-1, -1)) > 0) {
  341.             pvm_bufinfo(pvm_getrbuf(), (int *)0, &tag, &otid);
  342.             if (tag == SM_STTASK) {
  343.                 startem();
  344.  
  345.             } else {
  346.                 printf("tasker: unknown message tag %d\n", tag);
  347.             }
  348.         }    /* while nrecv >0 */
  349.  
  350.     /* we need a test here to catch nrecv sys errors */
  351.     if (mid<0) break;
  352.  
  353.     } /* while the select/nrecv loop */
  354.  
  355.     pvm_reg_tasker();
  356.     pvm_exit();
  357.     exit(0);
  358. }
  359.  
  360.  
  361. /*    startem()
  362. *
  363. *    Unpack task info from message and start it up.
  364. *
  365. *    SM_STTASK() {
  366. *        uint tid
  367. *        int flags
  368. *        string path
  369. *        int argc
  370. *        string argv[argc]
  371. *        int nenv
  372. *        string env[nenv]
  373. *    }
  374. */
  375.  
  376. int
  377. startem()
  378. {
  379.     int tid;
  380.     int flags;
  381.     char path[1024];
  382.     char buf[1024];
  383.     int ac;
  384.     char **av;
  385.     int nenv;
  386.     char **envp;
  387.     int i;
  388.     int pid;
  389.  
  390.     pvm_unpackf("%ud %d %s %d", &tid, &flags, path, &ac);
  391.     av = TALLOC(ac + 1, char *, 0);
  392.     av[ac] = 0;
  393.     for (i = 0; i < ac; i++) {
  394.         pvm_unpackf("%s", buf);
  395.         av[i] = STRALLOC(buf);
  396.     }
  397.     pvm_unpackf("%d", &nenv);
  398.     envp = TALLOC(nenv + 1, char *, 0);
  399.     envp[nenv] = 0;
  400.     for (i = 0; i < nenv; i++) {
  401.         pvm_unpackf("%s", buf);
  402.         envp[i] = STRALLOC(buf);
  403.     }
  404.     if (debug) {
  405.         printf("tid t%x flags %x path \"%s\"\n", tid, flags, path);
  406.         printf("argc %d\n", ac);
  407.         for (i = 0; i < ac; i++)
  408.             printf(" %d \"%s\"\n", i, av[i]);
  409.         printf("nenv %d\n", nenv);
  410.         for (i = 0; i < nenv; i++)
  411.             printf(" %d \"%s\"\n", i, envp[i]);
  412.     }
  413.  
  414.     if ((pid = dofork(path, ac, av, nenv, envp)) != -1) {
  415.         task_new(tid, pid);
  416.         if (debug)
  417.             printf("Forked %d\n", pid);
  418.  
  419.     } else {
  420.         pvm_packf("%+ %d %d %d %d %d %d", PvmDataFoo, tid, 0, 0, 0, 0, 0);
  421.         pvm_send(0x80000000, SM_TASKX);
  422.     }
  423.     return pid;
  424. }
  425.  
  426.  
  427. /*    dofork()
  428. *
  429. *    Fork and exec task, add changes to environment first.
  430. */
  431.  
  432. int
  433. dofork(path, argc, argv, nenv, envp)
  434.     char *path;
  435.     int argc;
  436.     char **argv;
  437.     int nenv;
  438.     char **envp;
  439. {
  440.     int pid;
  441.  
  442.     if (pid = fork()) {
  443.  
  444.     } else {
  445.         pvmendtask();
  446.         while (nenv-- > 0)
  447.             pvmputenv(envp[nenv]);
  448.         execv(path, argv);
  449. /*
  450.         execve(path, argv, envp);
  451. */
  452.         fprintf(stderr, "dofork() aaugh, bit it\n");
  453.         _exit(1);
  454.     }
  455.  
  456.     return pid;
  457. }
  458.  
  459.  
  460.